//
//Copyright 2001-2004 Stottler Henke Associates, Inc.
//All Rights Reserved.
////////////////////////////////////////////////////////////////////////////////

package com.stottlerhenke.simbionic.engine.parser;

import com.stottlerhenke.simbionic.engine.*;
import com.stottlerhenke.simbionic.engine.file.SB_StreamReader;
import com.stottlerhenke.simbionic.api.*;
import com.stottlerhenke.simbionic.api.SB_Param;

/**
 * Represents a single variable of type string.
 */
public class SB_VarString extends SB_Variable
{

  public SB_VarString() {
    _parameterValue = new SB_Param("");
  }
  
  public SB_VarString(String value){
    _parameterValue = new SB_Param( value );
  }
  
  public SB_VarString(SB_VarString var)
  throws SB_Exception
  {
    _parameterValue = new SB_Param( var.GetValue() );
  }

  public void load(SB_StreamReader reader,SB_SingletonBook book)
		throws SB_Exception
  {
    String expr = reader.readPString();

    if( book.getFileRegistry().getFormatVersion() >= 6 )
    {
      SB_Expression parsedExp = (SB_Expression)book.getParser().Parse(expr);

      // evaluating the expression without passing in an entity or execution frame is
      // only safe because the expression contains only constants!
      SB_Variable expValue = parsedExp.Evaluate(null, null);
      if (expValue.GetType() == SB_VarType.kString)
      {
        _parameterValue.setString( new String( ((SB_VarString) expValue).GetValue()) );
      }
      else
        throw new SB_Exception("Illegal initial value " + expr +" for string variable.");
    }
    else
    {
      _parameterValue.setString(expr);
    }
  }

  public void Copy(SB_VarString var) throws SB_Exception
  {
   // NOTE: must use c_str() or else we get a shallow copy of the String
    _parameterValue.copy(var.getSB_Param());
  }
  
  public SB_VarType GetType() { return SB_VarType.kString; }

  public void setSB_Param(SB_Param newParam) throws SB_Exception
  {
    newParam.getString();
    
    _parameterValue = newParam;
  }
  
  private void Free(){
  }

  public void SetValue( String value){
    // #OPT: a memory pool for strings
    _parameterValue.setString(value);
  }

  public String GetValue()
  throws SB_Exception
  {
    return _parameterValue.getString();
  }

  public static String GET_STRING(SB_Variable arg)
  throws SB_Exception
  {
    return ((SB_VarString)arg).GetValue();
  }
  
  public SB_Variable opAssign(SB_VarString var)throws SB_Exception {
    if (this != var) {
      Free();
      Copy(var);
    }
    return this;
  }
  
  public SB_Variable opOR( SB_Variable arg2)  {
    //FATAL( false, "Invalid operation on string variable");
    return null;
  }

  public SB_Variable opAND( SB_Variable arg2) throws SB_Exception  {
    //FATAL( false, "Invalid operation on string variable");
    return null;
  }

  public SB_Variable opGRTEq( SB_Variable arg2) throws SB_Exception  {
    SB_Variable result = null;

    if(arg2.GetType() == SB_VarType.kString)
      result = new SB_VarBoolean( GetValue().compareTo( GET_STRING(arg2)) >= 0 );
    return result;
  }

  public SB_Variable opLSSEq( SB_Variable arg2) throws SB_Exception  {
    SB_Variable result = null;
    if(arg2.GetType() == SB_VarType.kString)
      result = new SB_VarBoolean( GetValue().compareTo( GET_STRING(arg2)) <= 0 );
    return result;
  }

  public SB_Variable opNOTEq( SB_Variable arg2) throws SB_Exception  {
    SB_Variable result = null;

    if(arg2.GetType() == SB_VarType.kString)
      result = new SB_VarBoolean( GetValue().compareTo(GET_STRING(arg2)) != 0 );
    else if(arg2.GetType() == SB_VarType.kInvalid)
      result = new SB_VarBoolean( true );
    return result;
  }

  public SB_Variable equals( SB_Variable arg2) throws SB_Exception  {
    SB_Variable result = null;

    if (arg2.GetType() == SB_VarType.kString)
       result = new SB_VarBoolean( GetValue().compareTo(GET_STRING(arg2)) == 0 );
    else if( arg2.GetType() == SB_VarType.kInvalid)
       result = new SB_VarBoolean( false );
    return result;
  }

  public SB_Variable opGRT( SB_Variable arg2) throws SB_Exception  {
    SB_Variable result = null;

    if(arg2.GetType() == SB_VarType.kString)
      result = new SB_VarBoolean( GetValue().compareTo(GET_STRING(arg2)) > 0 );
    return result;
  }

  public SB_Variable opLSS( SB_Variable arg2) throws SB_Exception  {
    SB_Variable result = null;

    if(arg2.GetType() == SB_VarType.kString)
      result = new SB_VarBoolean( GetValue().compareTo(GET_STRING(arg2)) < 0 );
    return result;
  }

  public  SB_Variable opMOD( SB_Variable arg2) throws SB_Exception  {
    //FATAL( false, "Invalid operation on string variable");
    return null;
  }

  public SB_Variable opEXP( SB_Variable arg2) throws SB_Exception  {
    //FATAL( false, "Invalid operation on string variable");
    return null;
  }

  public SB_Variable opDIV( SB_Variable arg2) throws SB_Exception  {
    //FATAL( false, "Invalid operation on string variable");
    return null;
  }

  public SB_Variable opMUL( SB_Variable arg2) throws SB_Exception  {
    //FATAL( false, "Invalid operation on string variable");
    return null;
  }

  public SB_Variable opSUB( SB_Variable arg2) throws SB_Exception  {
    //FATAL( false, "Invalid operation on string variable");
    return null;
  }

  public SB_Variable opADD( SB_Variable arg2) throws SB_Exception  {
    SB_VarString result = null;
    String workStr;
    if(arg2.GetType() == SB_VarType.kFloat)
      workStr = GetValue() + Float.toString(SB_VarFloat.GET_FLOAT(arg2));
    else if(arg2.GetType() == SB_VarType.kInteger)
      workStr = GetValue() + Integer.toString(SB_VarInteger.GET_INTEGER(arg2));
    else if(arg2.GetType() == SB_VarType.kBoolean){
      String tmp = (SB_VarBoolean.GET_BOOLEAN(arg2) ? "true" : "false") ;
      workStr = GetValue() + tmp;
    }
    else if(arg2.GetType() == SB_VarType.kString)
      workStr = GetValue() + GET_STRING(arg2);
    else if(arg2.GetType() == SB_VarType.kVector)
    {
      SB_Vector vec = SB_VarVector.GET_VECTOR(arg2);
      workStr = GetValue() + "[" + Float.toString(vec.x) + "," + Float.toString(vec.y) + ","+ Float.toString(vec.z) + "]";
     }
    else if(arg2.GetType() == SB_VarType.kEntity)
      workStr =  GetValue() + "ENTITY-" + (SB_VarEntity.GET_ENTITY(arg2))._id;
    else if(arg2.GetType() == SB_VarType.kData)
    { 
      if( arg2.getSB_Param().getData() != null )
      	workStr = GetValue() + SB_VarData.GET_DATA(arg2).toString();
    	else
    	  workStr = GetValue() + SB_VarData.GET_DATA(arg2);
    }
    else if(arg2.GetType().getState() >= SB_VarType.kCLASS_START.getState())
    {
      if( arg2.getSB_Param().getData() != null)
        workStr = GetValue() + arg2.getSB_Param().getData().toString(); 
      else
        workStr = GetValue() + SB_VarData.GET_DATA(arg2);
    }
    else
    if(arg2.GetType() == SB_VarType.kArray)
    {
        workStr = arg2.toString();
    }
    else
      workStr = GetValue() + "<INVALID>";

    result = new SB_VarString( workStr );
    return result;
  }

  public SB_Variable opNOT() throws SB_Exception  {
    return new SB_VarBoolean( GetValue().length() == 0);
  }

  public SB_Variable opNEG() throws SB_Exception  {
    //FATAL( false, "Invalid operation on string variable");
    return null;
  }

  public boolean bool() throws SB_Exception{
    return GetValue().length() != 0 ;
  }

  public SB_Variable Clone() throws SB_Exception{
    return new SB_VarString(this);
  }
  public String toString()
  {
    try
    {
     if ( (GetValue()).length() > 0) {
       return GetValue();
     }
     else {
      return "";
     }
    }
    catch(SB_Exception ex)
    {
      return ex.toString();
    }
  }

}